<template>
    <div :class="className">
        <slot></slot>
    </div>
</template>

<script>
export default {
  provide() {
    let me = this;
    return {
      onAddPane: me.addPane,
      onDelPane: me.delPane,
      requestUpdate:me.requestUpdate
    };
  },
  props: {
    horizontal: Boolean
  },
  data() {
    return {
      panes: [],
      splits: [],
      touch: {
        splitIndex: null,
        point: null,
        prevPaneSize: null,
        nextPaneSize: null
      },
      activeSplitIndex: null,
      point: [],
      paneClassName: "des-layout-pane",
      splitClassName: "des-layout-split"
    };
  },
  computed: {
    className() {
      return {
        "des-layout": true,
        "des-layout-horizontal": this.horizontal
      };
    }
  },
  mounted() {},
  methods: {
    addPane(pane) {
      this.panes.push(pane);
      this.resetSplit();
      this.updateSize();
    },
    delPane(pane) {
      for (let i = 0, l = this.panes.length; i < l; i++) {
        if (this.panes[i] == pane) {
          this.panes.splice(i, 1);
        }
      }
      this.resetSplit();
      this.updateSize();
    },
    resetSplit() {
      let { splitClassName, paneClassName } = this;
      let subs = [].slice.call(this.$el.children);
      let splits = subs.filter(
        item => item.className.indexOf(splitClassName) > -1
      );
      //过滤掉不可视的面板
      let panes = subs.filter(
        item => item.className.indexOf(paneClassName) > -1//&&item.style.display!='none'
      );
      let i = 0,
        l = 0;
      //清空split 
      for (i = 0, l = splits.length; i < l; i++) {
        splits[i].onmousedown = undefined;
        splits[i].onclick = undefined;
        splits[i].ondblclick = undefined;
        splits[i].remove();
      }
      let split_els = [];
      //按可视面板创建 split
      for (i = 0, l = panes.length; i < l; i++) {
        let el = document.createElement("div");
        el.className = splitClassName;
        el.index = i;
        el.style.display = panes[i].style.display == 'none'?'none':'';
        panes[i].index = i; //设索引
        if (panes[i + 1]) {
          el.onmousedown = this.onSplitMousedown;
          split_els.push(el);
          this.$el.insertBefore(el, panes[i + 1]);
        }
      }
      //重排序
      this.panes.sort((a, b) => {
        return a.$el.index - b.$el.index;
      });
      this.$set(this, "splits", split_els);
    },
    updateSize() {
      let { panes, horizontal } = this,
        len = panes.length,
        boxWidth = horizontal?this.$el.offsetHeight:this.$el.offsetWidth,
        residue = 100;
      let showPanes = panes.filter(item=>{
        return item.$el.style.display!=='none'
      })
      
      //计算出所有 split 占用的比例
      let splitSize = boxWidth?(showPanes.length-1)*5/boxWidth:0;
      if(isNaN(splitSize))debugger
      // console.log(splitSize,showPanes.length,'this.$el.offsetWidth:',this.$el.offsetWidth)
      //除去split 占比例的剩余大小
      residue -=splitSize;
      //过滤出没设大小的区域，并更新有大小区域
      let unSizePanes = panes.filter((item, i) => {
        if (item.size === undefined) {
          return item;
        } else {
          item.updateSize({
            [horizontal ? "height" : "width"]: item.size + "%"
          });
          residue -= item.$el.style.display=='none'?0:item.size;
        }
      });
      for (let i = 0, l = unSizePanes.length; i < l; i++) {
        unSizePanes[i].updateSize({
          [horizontal ? "height" : "width"]: residue / l + "%"
        });
      }
    },
    requestUpdate(){
      this.resetSplit();
      this.updateSize();
    },
    getCurrentMouseDrag(event) {
      const rect = this.$el.getBoundingClientRect();
      const { clientX, clientY } =
        "ontouchstart" in window && event.touches ? event.touches[0] : event;
      return {
        x: clientX - rect.left,
        y: clientY - rect.top
      };
    },
    //计算面板大小
    calculatePanesSize(diffX, diffY) {
      let prevPane, nextPane;
      let { splits, touch, panes, horizontal } = this;

      prevPane = panes[touch.splitIndex];
      // nextPane = panes[touch.splitIndex + 1];
      //查找下一个可视的pane
      let i = 1;
      nextPane = panes[touch.splitIndex + i];
      while(nextPane.$el.style.display=='none'){
        i++;
        nextPane = panes[touch.splitIndex + i]
      }

      //向上 正 向上拖动, 向左 正 向左拖动
      if (horizontal) {
        let layoutHeight = this.$el.offsetHeight;
        let diffRatio = Math.abs(diffY) / layoutHeight * 100;
        let prevRatio = touch.prevPaneSize / layoutHeight * 100;
        let nextRatio = touch.nextPaneSize / layoutHeight * 100;
        let ratio2 = prevRatio + nextRatio;
        if (diffY > 0) {
          //向左边拖动
          let p1 = prevRatio - diffRatio;
          let p2 = nextRatio + diffRatio;
          prevPane.updateSize({
            height: `${p1 > 0 ? p1 : 0}%`
          });
          nextPane.updateSize({
            height: `${p2 > ratio2 ? ratio2 : p2}%`
          });
        } else {
          //向右边拖动
          let p1 = prevRatio + diffRatio;
          let p2 = nextRatio - diffRatio;
          prevPane.updateSize({
            height: `${p1 > ratio2 ? ratio2 : p1}%`
          });
          nextPane.updateSize({
            height: `${p2 > 0 ? p2 : 0}%`
          });
        }
      } else {
        let layoutWidth = this.$el.offsetWidth;
        let diffRatio = Math.abs(diffX) / layoutWidth * 100;
        let prevRatio = touch.prevPaneSize / layoutWidth * 100;
        let nextRatio = touch.nextPaneSize / layoutWidth * 100;
        let ratio2 = prevRatio + nextRatio;
        if (diffX > 0) {
          //向左边拖动
          let p1 = prevRatio - diffRatio;
          let p2 = nextRatio + diffRatio;
          prevPane.updateSize({
            width: `${p1 > 0 ? p1 : 0}%`
          });
          nextPane.updateSize({
            width: `${p2 > ratio2 ? ratio2 : p2}%`
          });
        } else {
          //向右边拖动
          let p1 = prevRatio + diffRatio;
          let p2 = nextRatio - diffRatio;
          prevPane.updateSize({
            width: `${p1 > ratio2 ? ratio2 : p1}%`
          });
          nextPane.updateSize({
            width: `${p2 > 0 ? p2 : 0}%`
          });
        }
      }
      // console.log(diffX, diffY);
    },
    bindEvents() {
      document.addEventListener("mousemove", this.onMouseMove, {
        passive: false
      });
      document.addEventListener("mouseup", this.onMouseUp);
      // Passive: false to prevent scrolling while touch dragging.
      if ("ontouchstart" in window) {
        document.addEventListener("touchmove", this.onMouseMove, {
          passive: false
        });
        document.addEventListener("touchend", this.onMouseUp);
      }
    },
    unbindEvents() {
      document.removeEventListener("mousemove", this.onMouseMove, {
        passive: false
      });
      document.removeEventListener("mouseup", this.onMouseUp);
      if ("ontouchstart" in window) {
        document.removeEventListener("touchmove", this.onMouseMove, {
          passive: false
        });
        document.removeEventListener("touchend", this.onMouseUp);
      }
    },
    onSplitMousedown(evt) {
      this.bindEvents();
      const { clientX, clientY } =
        "ontouchstart" in window && event.touches ? event.touches[0] : event;
      let index = evt.target.index;
      this.touch.point = [clientX, clientY];
      this.touch.splitIndex = index;
      //查找下一个可视的pane
      let i = 1;
      let nextPane = this.panes[index + i];
      while(nextPane.$el.style.display=='none'){
        i++;
        nextPane = this.panes[index + i]
      }

      if (this.horizontal) {
        this.touch.prevPaneSize = this.panes[index].$el.offsetHeight;
        this.touch.nextPaneSize = nextPane.$el.offsetHeight;
      } else {
        this.touch.prevPaneSize = this.panes[index].$el.offsetWidth;
        this.touch.nextPaneSize = nextPane.$el.offsetWidth;
      }

      //   console.log(clientX,clientY)
      //console.log("onSplitMousedown", evt.target, evt.target.index);
    },
    onMouseUp(evt) {
      this.activeSplitIndex = null;
      this.unbindEvents();
       this.$emit(
        "resized",
        this.panes.map(pane => ({
          min: pane.min,
          max: pane.max,
          size: pane.size
        }))
      );
    },
    onMouseMove(evt) {
      evt.preventDefault();
      //   let rect = this.getCurrentMouseDrag(evt);
      const { clientX, clientY } =
        "ontouchstart" in window && evt.touches ? evt.touches[0] : evt;
      this.calculatePanesSize(
        this.touch.point[0] - clientX,
        this.touch.point[1] - clientY
      );
      this.$emit(
        "resizing",
        this.panes.map(pane => ({
          min: pane.min,
          max: pane.max,
          size: pane.size
        }))
      );
    }
  }
};
</script>

<style lang="less">
.des-layout {
  height: 100%;
  width: 100%;
  display: flex;
  > .des-layout-split {
    width: 5px;
    cursor: col-resize;
    position: relative;
    text-align: center;
    border: 1px solid #eee;
    border-width: 0 1px;
    &:hover {
      background: #2672ff;
    }
    &::before,
    &::after {
      content: "";
      width: 1px;
      height: 30px;
      line-height: 1;
      background: #ccc;
      position: absolute;

      top: 50%;
      margin: -15px 0 0 0;
    }
    &::before {
      left: 1px;
    }
    &::after {
      right: 1px;
    }
  }
  &.des-layout-horizontal {
    flex-direction: column;
    > .des-layout-split {
      width: auto;
      height: 5px;
      cursor: row-resize;
      border: 1px solid #eee;
      border-width:1px 0;
      &::before,
      &::after {
        height: 1px;
        width: 30px;

        left: 50%;
        margin: 0 0 0 -15px;
      }

      &::before {
        top: 1px;
      }
      &::after {
        top: auto;
        bottom: 1px;
      }
    }
  }
}
</style>